package com.far.game.xiuzhen.interceptor;


import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;


import com.far.game.xiuzhen.common.dto.Visitor;
import com.far.game.xiuzhen.common.utils.AppUtil;
import com.far.game.xiuzhen.common.utils.JWTUtil;
import com.far.game.xiuzhen.common.utils.JWTUtils;
import com.far.game.xiuzhen.common.utils.Optional;
import com.far.game.xiuzhen.gm.web.BaseController;
import com.far.tools.constant.ReturnStat;
import com.far.tools.net.http.transfer.ResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Handler;
import java.util.stream.Collectors;

/*
 * @description: TODO
 * @author mike/Fang.J/Q184377367
 * @date 2022/4/12 1:28
 */
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {

    //不需要验证token的接口
    private Set<String> skipTokenCheckUrl = new HashSet<>(
            Arrays.asList(
                    "/api/admin/test/test2",
                    "/api/admin/test/test",
                    "/api/admin/user/getToken",
//                    "/api/admin/user/add",
                    "/api/admin/user/test",
                    "/api/admin/user/login",
                    "/api/admin/user/reg",
//                    "/far-user/create-guest-token",
//                    "/far-user/register",
//                    "/far/api/user/get-user-at-shop",
//                    "/far/api/home/get-grid",
//                    "/far/api/category/lists",
//                    "/far/api/user/test-login",
//                    "/far/store/passport/login",
                    "/error"
//                    "/api/admin/dict/data/character-properties-add",
//                    "/api/admin/dict/data/character-properties-update",
//                    "/api/admin/user/tools/conver-json",
//                    "/api/admin/dict/data/character-properties-query",
//                    "/api/admin/dict/data/character-properties-remove",
//                    "/api/admin/role/skill/skill-add",
//                    "/api/admin/role/skill/skill-update",
//                    "/api/admin/role/skill/skill-remove",
//                    "/api/admin/role/skill/skill-query",
//                    "/api/admin/role/skill/skill-bufs-add",
//                    "/api/admin/role/skill/skill-bufs-update",
//                    "/api/admin/role/skill/skill-bufs-remove",
//                    "/api/admin/role/skill/skill-bufs-query",
//                    "/api/admin/servers/servers-add",
//                    "/api/admin/servers/servers-update",
//                    "/api/admin/servers/servers-remove",
//                    "/api/admin/servers/servers-query",
//                    "/api/admin/user/partner/user-partner-add",
//                    "/api/admin/user/partner/user-partner-update",
//                    "/api/admin/user/partner/user-partner-remove",
//                    "/api/admin/user/partner/user-partner-query",
//                    "/api/admin/user/partner/import",
//                    "/api/admin/user/partner/eptExcel"






            )
    );

    Optional<String> token;

    String requestUrl;

    String methodType;

    private void responseResult(HttpServletResponse response, ResultData<?> result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "application/json");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
//        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType("application/json;charset=UTF-8");
//        ServletOutputStream out = null;
        PrintWriter writer = null;
        try {
            // JSON.toJSONString(result)要获取完整的json字符串，每一个字段都要有set和get方法，不然会缺少某个字段
//            response.getWriter().write(JSON.toJSONString(result));
            writer = response.getWriter();
//            writer.write(result.toString());

            writer.write(JSONUtil.toJsonStr(result));
            writer.flush();
        } catch (IOException ex) {
            // logger.error(ex.getMessage());
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * @param token
     * @param handler
     * @description: 访问者注入父控制器
     * @return: void
     * @author mike/Fang.J/Q184377367
     * @date: 2022/7/15 4:25
     */
    public void injectParentController(Optional<String> token, Object handler) throws Exception {
        Method hm = ReflectUtil.getMethod(HandlerMethod.class, "getBean");
        Object ctl = hm.invoke(handler);
       Method setVisitorMt = ReflectUtil.getMethod(BaseController.class, "setVisitor", Visitor.class);
       // Method setVisitorMt = ReflectUtil.getMethodOfObj(ctl,"setVisitor", Visitor.class);
        setVisitorMt.invoke(ctl, JWTUtil.getTokenForVisitor(token.getVal()));
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        log.info("进入LoginInterceptor拦截器---------------------------------------");


        //添加跨域CORS
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "3600");



        //response.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type,token");
        //response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");

        requestUrl = request.getRequestURI();
        methodType = request.getMethod();

        //OPTIOONS不处理
        if (methodType.equals("OPTIONS")) return true;


        String s = request.getHeader("token");

        token = Optional.of(request.getHeader("token")).orElse(request.getHeader("X-Token"));


        List<String> turk = skipTokenCheckUrl.stream().filter(e -> {
            return e.equals(requestUrl);
        }).collect(Collectors.toList());

        //不是HandlerMethod类型不处理
//        if (!(handler instanceof HandlerMethod)) return true;

        //设置了URL就不需要验证TOKEN
        if (turk.size() > 0) {
            return true;
        }

        if (StringUtils.isEmpty(token.getVal())) {
            responseResult(response, ResultData.error(ReturnStat.TOKEN_FAILED,String.format("url:%s ->token cannot be empty ", requestUrl)));
            return false;
        }

        this.injectParentController(token,handler);

        return true;
    }

////    @Override
////    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        // System.out.println("后置方法执行..");
//    }
//
//    @Override
//    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        // System.out.println("完成方法执行..");
//    }
}